package com.ruoyi.manage.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Date;
import java.util.Calendar;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.manage.mapper.CrMatchingRecordMapper;
import com.ruoyi.manage.mapper.CrRecruitmentMapper;
import com.ruoyi.manage.mapper.CrStudentProfileMapper;
import com.ruoyi.manage.mapper.CrClubMapper;
import com.ruoyi.manage.domain.CrMatchingRecord;
import com.ruoyi.manage.domain.CrRecruitment;
import com.ruoyi.manage.domain.CrStudentProfile;
import com.ruoyi.manage.domain.CrClub;
import com.ruoyi.manage.service.ICrMatchingRecordService;

/**
 * 智能匹配记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-09-24
 */
@Service
public class CrMatchingRecordServiceImpl implements ICrMatchingRecordService 
{
    private static final Logger log = LoggerFactory.getLogger(CrMatchingRecordServiceImpl.class);
    
    @Autowired
    private CrMatchingRecordMapper crMatchingRecordMapper;
    
    @Autowired
    private CrRecruitmentMapper crRecruitmentMapper;
    
    @Autowired
    private CrStudentProfileMapper crStudentProfileMapper;
    
    @Autowired
    private CrClubMapper crClubMapper;
    
    // 获取学生档案信息
    private CrStudentProfile getStudentProfileByUserId(Long userId) {
        return crStudentProfileMapper.selectCrStudentProfileByUserId(userId);
    }
    
    // 获取社团信息
    private CrClub getClubById(Long clubId) {
        return crClubMapper.selectCrClubByClubId(clubId);
    }
    
    // 解析JSON格式的技能数据
    private List<String> parseJsonSkills(String skillsJson) {
        List<String> skills = new ArrayList<>();
        if (skillsJson == null || skillsJson.trim().isEmpty()) {
            return skills;
        }
        
        try {
            // 处理可能的JSON数组
            if (skillsJson.startsWith("[")) {
                JSONArray jsonArray = JSONArray.parseArray(skillsJson);
                for (int i = 0; i < jsonArray.size(); i++) {
                    skills.add(jsonArray.getString(i).trim());
                }
            } 
            // 处理字符串列表（逗号分隔）
            else if (skillsJson.contains(",")) {
                String[] skillArray = skillsJson.split(",");
                for (String skill : skillArray) {
                    skills.add(skill.trim());
                }
            } 
            // 处理单个技能
            else {
                skills.add(skillsJson.trim());
            }
        } catch (Exception e) {
            log.error("解析技能数据出错: {}", skillsJson, e);
        }
        
        return skills;
    }
    
    // 解析JSON格式的兴趣爱好数据
    private List<String> parseJsonInterests(String interestsJson) {
        List<String> interests = new ArrayList<>();
        if (interestsJson == null || interestsJson.trim().isEmpty()) {
            return interests;
        }
        
        try {
            // 处理可能的JSON数组
            if (interestsJson.startsWith("[")) {
                JSONArray jsonArray = JSONArray.parseArray(interestsJson);
                for (int i = 0; i < jsonArray.size(); i++) {
                    interests.add(jsonArray.getString(i).trim());
                }
            } 
            // 处理字符串列表（逗号分隔）
            else if (interestsJson.contains(",")) {
                String[] interestArray = interestsJson.split(",");
                for (String interest : interestArray) {
                    interests.add(interest.trim());
                }
            } 
            // 处理单个兴趣
            else {
                interests.add(interestsJson.trim());
            }
        } catch (Exception e) {
            log.error("解析兴趣爱好数据出错: {}", interestsJson, e);
        }
        
        return interests;
    }
    
    // 解析JSON格式的可用时间数据
    private Map<String, List<String>> parseJsonAvailableTime(String availableTimeJson) {
        Map<String, List<String>> timeMap = new HashMap<>();
        if (availableTimeJson == null || availableTimeJson.trim().isEmpty()) {
            return timeMap;
        }
        
        try {
            // 处理JSON对象格式的时间数据
            JSONObject jsonObject = JSONObject.parseObject(availableTimeJson);
            for (String day : jsonObject.keySet()) {
                Object value = jsonObject.get(day);
                
                if (value instanceof JSONArray) {
                    JSONArray timeArray = (JSONArray) value;
                    List<String> times = new ArrayList<>();
                    for (int i = 0; i < timeArray.size(); i++) {
                        times.add(timeArray.getString(i).trim());
                    }
                    timeMap.put(day, times);
                } else if (value instanceof String) {
                    String timeStr = ((String) value).trim();
                    if (timeStr.contains(",")) {
                        List<String> times = Arrays.asList(timeStr.split(","));
                        timeMap.put(day, times.stream().map(String::trim).collect(Collectors.toList()));
                    } else if (!timeStr.isEmpty()) {
                        timeMap.put(day, Collections.singletonList(timeStr));
                    }
                }
            }
        } catch (Exception e) {
            log.error("解析可用时间数据出错: {}", availableTimeJson, e);
        }
        
        return timeMap;
    }
    
    // 从社团信息中提取关键词
    private List<String> extractClubKeywords(CrClub club) {
        List<String> keywords = new ArrayList<>();
        
        // 提取社团名称中的关键词
        if (club.getClubName() != null && !club.getClubName().trim().isEmpty()) {
            String clubName = club.getClubName();
            // 移除"社"、"协会"、"俱乐部"等后缀
            clubName = clubName.replaceAll("[社协会俱乐部]", "").trim();
            keywords.add(clubName);
        }
        
        // 提取社团描述中的关键词
        if (club.getDescription() != null && !club.getDescription().trim().isEmpty()) {
            // 简单提取一些关键词，实际应用中可以使用更复杂的NLP方法
            String[] importantWords = {"音乐", "舞蹈", "科技", "编程", "文学", "体育", "绘画", "摄影", "志愿者", "环保", "英语", "数学", "物理"};
            for (String word : importantWords) {
                if (club.getDescription().contains(word)) {
                    keywords.add(word);
                }
            }
        }        
        
        // 提取社团类型
        if (club.getClubType() != null && !club.getClubType().trim().isEmpty()) {
            keywords.add(club.getClubType());
        }
        
        return keywords;
    }
    
    // 根据社团类型调整分数
    private double adjustScoreByClubType(CrClub club, CrStudentProfile studentProfile) {
        double score = 0;
        
        // 根据专业与社团类型的匹配度调整分数
        if (club.getClubType() != null && studentProfile.getMajor() != null) {
            String clubType = club.getClubType().toLowerCase();
            String major = studentProfile.getMajor().toLowerCase();
            
            // 定义一些专业与社团类型的匹配关系
            Map<String, List<String>> majorTypeMap = new HashMap<>();
            majorTypeMap.put("音乐", Arrays.asList("音乐", "艺术", "表演"));
            majorTypeMap.put("舞蹈", Arrays.asList("舞蹈", "艺术", "表演"));
            majorTypeMap.put("科技", Arrays.asList("计算机", "软件", "电子", "自动化", "通信"));
            majorTypeMap.put("文学", Arrays.asList("中文", "文学", "新闻", "编辑"));
            majorTypeMap.put("英语", Arrays.asList("英语", "外语", "翻译"));
            
            for (Map.Entry<String, List<String>> entry : majorTypeMap.entrySet()) {
                if (clubType.contains(entry.getKey())) {
                    for (String relatedMajor : entry.getValue()) {
                        if (major.contains(relatedMajor)) {
                            score = 3; // 专业匹配加3分
                            break;
                        }
                    }
                }
            }
        }
        
        return score;
    }
    
    // 计算时间重叠度
    private double calculateTimeOverlap(Map<String, List<String>> studentAvailableTime, String recruitmentWorkTime) {
        // 默认基础分
        double baseScore = 75.0;
        
        // 简化的时间匹配逻辑
        // 实际应用中需要更复杂的时间解析和匹配算法
        String[] workDays = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        int matchedDays = 0;
        int totalMentionedDays = 0;
        
        // 检查招聘信息中提到的工作日
        for (String day : workDays) {
            if (recruitmentWorkTime.contains(day)) {
                totalMentionedDays++;
                if (studentAvailableTime.containsKey(day)) {
                    matchedDays++;
                }
            }
        }
        
        // 如果招聘信息中提到了具体工作日，计算匹配度
        if (totalMentionedDays > 0) {
            double matchPercentage = (double) matchedDays / totalMentionedDays;
            // 根据匹配度调整分数
            baseScore = 60 + (matchPercentage * 40); // 60-100分
        }
        
        // 考虑特殊情况：灵活时间
        if (recruitmentWorkTime.contains("灵活") || recruitmentWorkTime.contains("自由")) {
            baseScore = Math.min(100, baseScore + 10); // 灵活时间额外加10分
        }
        
        return baseScore;
    }

    @Override
    public CrMatchingRecord selectCrMatchingRecordByMatchingId(Long matchingId)
    {
        return crMatchingRecordMapper.selectCrMatchingRecordByRecordId(matchingId);
    }

    @Override
    public List<CrMatchingRecord> selectCrMatchingRecordList(CrMatchingRecord crMatchingRecord)
    {
        return crMatchingRecordMapper.selectCrMatchingRecordList(crMatchingRecord);
    }

    @Override
    @Transactional
    public int insertCrMatchingRecord(CrMatchingRecord crMatchingRecord)
    {
        crMatchingRecord.setCreateTime(DateUtils.getNowDate());
        return crMatchingRecordMapper.insertCrMatchingRecord(crMatchingRecord);
    }

    @Override
    @Transactional
    public int updateCrMatchingRecord(CrMatchingRecord crMatchingRecord)
    {
        crMatchingRecord.setUpdateTime(DateUtils.getNowDate());
        return crMatchingRecordMapper.updateCrMatchingRecord(crMatchingRecord);
    }

    @Override
    @Transactional
    public int deleteCrMatchingRecordByMatchingIds(Long[] matchingIds)
    {
        return crMatchingRecordMapper.deleteCrMatchingRecordByRecordIds(matchingIds);
    }

    @Override
    @Transactional
    public int deleteCrMatchingRecordByMatchingId(Long matchingId)
    {
        return crMatchingRecordMapper.deleteCrMatchingRecordByRecordId(matchingId);
    }

    @Override
    @Transactional
    public List<CrMatchingRecord> generateMatchingRecommendations(Long studentId, int limit)
    {
        List<CrMatchingRecord> recommendations = new ArrayList<>();
        
        // 获取活跃的招聘信息
        CrRecruitment queryParam = new CrRecruitment();
        queryParam.setStatus("0"); // 0表示招聘中
        List<CrRecruitment> activeRecruitments = crRecruitmentMapper.selectActiveRecruitmentList(queryParam);

        for (CrRecruitment recruitment : activeRecruitments) {
            // 分别计算各项匹配分数
            BigDecimal skillScore = calculateSkillMatchingScore(studentId, recruitment.getRecruitmentId());
            BigDecimal interestScore = calculateInterestMatchingScore(studentId, recruitment.getClubId());
            BigDecimal timeScore = calculateTimeMatchingScore(studentId, recruitment.getRecruitmentId());
            
            // 计算总分（与calculateMatchingScore方法保持一致的计算逻辑）
            BigDecimal totalScore = skillScore.multiply(new BigDecimal("0.4"))
                    .add(interestScore.multiply(new BigDecimal("0.3")))
                    .add(timeScore.multiply(new BigDecimal("0.2")))
                    .add(new BigDecimal("80").multiply(new BigDecimal("0.1")))
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
            
            if (totalScore.compareTo(new BigDecimal("60")) >= 0) {
                CrMatchingRecord record = new CrMatchingRecord();
                record.setUserId(studentId);
                record.setClubId(recruitment.getClubId());
                record.setRecruitmentId(recruitment.getRecruitmentId());
                record.setMatchScore(totalScore);
                
                // 保存各项详细评分
                record.setSkillMatchScore(skillScore);
                record.setInterestMatchScore(interestScore);
                record.setTimeMatchScore(timeScore);
                
                // 计算其他因素分（简单实现，可以根据实际需求调整）
                BigDecimal otherScore = new BigDecimal("80").setScale(2, BigDecimal.ROUND_HALF_UP);
                record.setOtherFactorsScore(otherScore);
                
                // 生成推荐理由
                record.setRecommendationReason(generateRecommendationReason(skillScore, interestScore, timeScore, recruitment));
                
                // 生成匹配详情（JSON格式）
                record.setMatchDetails(generateMatchDetails(skillScore, interestScore, timeScore, otherScore));
                
                record.setIsRecommended("Y");
                record.setCreateTime(DateUtils.getNowDate());

                recommendations.add(record);
            }
        }

        if (!recommendations.isEmpty()) {
            // 按匹配分数降序排序
            recommendations.sort((r1, r2) -> r2.getMatchScore().compareTo(r1.getMatchScore()));
            // 限制返回数量
            if (recommendations.size() > limit) {
                recommendations = recommendations.subList(0, limit);
            }
            
            try {
                batchCreateMatchingRecords(recommendations);
            } catch (Exception e) {
                // 如果出现重复键异常，可以尝试更新现有记录
                log.warn("批量创建匹配记录时出错：{}", e.getMessage());
                // 可以根据需要实现更新逻辑
            }
        }

        return recommendations;
    }

    @Override
    public List<CrMatchingRecord> generateRecruitmentRecommendations(Long recruitmentId, int limit)
    {
        return crMatchingRecordMapper.selectBestMatchedStudents(null, recruitmentId, limit);
    }

    @Override
    public BigDecimal calculateMatchingScore(Long studentId, Long recruitmentId)
    {
        BigDecimal skillScore = calculateSkillMatchingScore(studentId, recruitmentId);
        BigDecimal interestScore = calculateInterestMatchingScore(studentId, null);
        BigDecimal timeScore = calculateTimeMatchingScore(studentId, recruitmentId);

        BigDecimal totalScore = skillScore.multiply(new BigDecimal("0.4"))
                .add(interestScore.multiply(new BigDecimal("0.3")))
                .add(timeScore.multiply(new BigDecimal("0.2")))
                .add(new BigDecimal("80").multiply(new BigDecimal("0.1")));

        return totalScore.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    @Override
    public BigDecimal calculateSkillMatchingScore(Long studentId, Long recruitmentId) {
        // 获取学生技能信息
        CrStudentProfile studentProfile = getStudentProfileByUserId(studentId);
        if (studentProfile == null) {
            log.warn("未找到学生档案信息: userId={}", studentId);
            return new BigDecimal(60).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        // 获取招聘技能要求
        CrRecruitment recruitment = crRecruitmentMapper.selectCrRecruitmentByRecruitmentId(recruitmentId);
        if (recruitment == null) {
            log.warn("未找到招聘信息: recruitmentId={}", recruitmentId);
            return new BigDecimal(60).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        try {
            // 解析学生技能和招聘技能要求
            List<String> studentSkills = parseJsonSkills(studentProfile.getSkills());
            List<String> requiredSkills = parseJsonSkills(recruitment.getRequiredSkills());
            
            // 如果招聘没有技能要求，给一个基础分
            if (requiredSkills.isEmpty()) {
                return new BigDecimal(80).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            
            // 计算匹配度：匹配技能数/总技能要求数
            int matchedSkills = 0;
            for (String requiredSkill : requiredSkills) {
                if (studentSkills.contains(requiredSkill)) {
                    matchedSkills++;
                }
            }
            
            // 计算基础匹配分
            double matchPercentage = (double) matchedSkills / requiredSkills.size();
            double baseScore = 60 + (matchPercentage * 40); // 60-100分
            
            // 考虑专业相关性加分
            if (recruitment.getRequirements() != null && studentProfile.getMajor() != null) {
                String requirementsLower = recruitment.getRequirements().toLowerCase();
                String majorLower = studentProfile.getMajor().toLowerCase();
                if (requirementsLower.contains(majorLower)) {
                    baseScore = Math.min(100, baseScore + 5); // 专业匹配额外加5分
                }
            }
            
            return new BigDecimal(baseScore).setScale(2, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            log.error("计算技能匹配分数出错", e);
            return new BigDecimal(70).setScale(2, BigDecimal.ROUND_HALF_UP); // 出错时返回基础分
        }
    }
    
    @Override
    public BigDecimal calculateInterestMatchingScore(Long studentId, Long clubId) {
        // 获取学生兴趣信息
        CrStudentProfile studentProfile = getStudentProfileByUserId(studentId);
        if (studentProfile == null) {
            log.warn("未找到学生档案信息: userId={}", studentId);
            return new BigDecimal(60).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        // 获取社团信息
        CrClub club = getClubById(clubId);
        if (club == null) {
            log.warn("未找到社团信息: clubId={}", clubId);
            return new BigDecimal(60).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        try {
            // 解析学生兴趣
            List<String> studentInterests = parseJsonInterests(studentProfile.getInterests());
            
            // 从社团信息中提取关键词
            List<String> clubKeywords = extractClubKeywords(club);
            
            // 如果学生没有兴趣信息，给一个基础分
            if (studentInterests.isEmpty()) {
                return new BigDecimal(65).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            
            // 计算兴趣匹配度
            int matchedInterests = 0;
            for (String interest : studentInterests) {
                for (String keyword : clubKeywords) {
                    if (interest.toLowerCase().contains(keyword.toLowerCase()) || 
                        keyword.toLowerCase().contains(interest.toLowerCase())) {
                        matchedInterests++;
                        break;
                    }
                }
            }
            
            // 计算基础匹配分
            double matchPercentage = (double) matchedInterests / studentInterests.size();
            double baseScore = 60 + (matchPercentage * 40); // 60-100分
            
            // 根据社团类型调整分数
            double typeAdjustmentScore = adjustScoreByClubType(club, studentProfile);
            if (typeAdjustmentScore > 0) {
                baseScore = Math.min(100, baseScore + typeAdjustmentScore); // 特定类型社团额外加分
            }
            
            return new BigDecimal(baseScore).setScale(2, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            log.error("计算兴趣匹配分数出错", e);
            return new BigDecimal(65).setScale(2, BigDecimal.ROUND_HALF_UP); // 出错时返回基础分
        }
    }
    
    @Override
    public BigDecimal calculateTimeMatchingScore(Long studentId, Long recruitmentId) {
        // 获取学生时间信息
        CrStudentProfile studentProfile = getStudentProfileByUserId(studentId);
        if (studentProfile == null) {
            log.warn("未找到学生档案信息: userId={}", studentId);
            return new BigDecimal(75).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        // 获取招聘时间信息
        CrRecruitment recruitment = crRecruitmentMapper.selectCrRecruitmentByRecruitmentId(recruitmentId);
        if (recruitment == null) {
            log.warn("未找到招聘信息: recruitmentId={}", recruitmentId);
            return new BigDecimal(75).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        
        try {
            // 解析学生可用时间和招聘工作时间
            Map<String, List<String>> studentAvailableTime = parseJsonAvailableTime(studentProfile.getAvailableTime());
            String recruitmentWorkTime = recruitment.getWorkTime();
            
            // 如果学生没有时间信息，给一个基础分
            if (studentAvailableTime.isEmpty()) {
                return new BigDecimal(80).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            
            // 如果招聘没有工作时间要求，给一个较高的基础分
            if (recruitmentWorkTime == null || recruitmentWorkTime.trim().isEmpty()) {
                return new BigDecimal(85).setScale(2, BigDecimal.ROUND_HALF_UP);
            }
            
            // 计算时间匹配度
            double timeMatchScore = calculateTimeOverlap(studentAvailableTime, recruitmentWorkTime);
            
            return new BigDecimal(timeMatchScore).setScale(2, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            log.error("计算时间匹配分数出错", e);
            return new BigDecimal(80).setScale(2, BigDecimal.ROUND_HALF_UP); // 出错时返回基础分
        }
    }

    @Override
    @Transactional
    public int batchCreateMatchingRecords(List<CrMatchingRecord> matchingRecords)
    {
        if (matchingRecords == null || matchingRecords.isEmpty()) {
            return 0;
        }

        Date now = DateUtils.getNowDate();
        for (CrMatchingRecord record : matchingRecords) {
            record.setCreateTime(now);
        }

        return crMatchingRecordMapper.batchInsertMatchingRecords(matchingRecords);
    }

    @Override
    @Transactional
    public int updateMatchingStatus(Long matchingId, String status)
    {
        CrMatchingRecord record = crMatchingRecordMapper.selectCrMatchingRecordByRecordId(matchingId);
        if (record == null) {
            throw new RuntimeException("匹配记录不存在");
        }

        record.setUpdateTime(DateUtils.getNowDate());

        return crMatchingRecordMapper.updateCrMatchingRecord(record);
    }

    @Override
    public List<CrMatchingRecord> selectMatchingsByStudentId(Long studentId, String status)
    {
        return crMatchingRecordMapper.selectStudentMatchingRecords(studentId, status);
    }

    @Override
    public List<CrMatchingRecord> selectMatchingsByClubId(Long clubId, String status)
    {
        return crMatchingRecordMapper.selectClubMatchingRecords(clubId, status);
    }

    @Override
    public List<CrMatchingRecord> selectMatchingsByRecruitmentId(Long recruitmentId, String status)
    {
        CrMatchingRecord queryParam = new CrMatchingRecord();
        queryParam.setRecruitmentId(recruitmentId);
        return crMatchingRecordMapper.selectCrMatchingRecordList(queryParam);
    }

    @Override
    public List<CrMatchingRecord> getHighMatchingRecords(BigDecimal threshold, int limit)
    {
        CrMatchingRecord queryParam = new CrMatchingRecord();
        List<CrMatchingRecord> allRecords = crMatchingRecordMapper.selectCrMatchingRecordList(queryParam);

        return allRecords.stream()
                .filter(record -> record.getMatchScore() != null && 
                        record.getMatchScore().compareTo(threshold) >= 0)
                .sorted((r1, r2) -> r2.getMatchScore().compareTo(r1.getMatchScore()))
                .limit(limit)
                .collect(java.util.stream.Collectors.toList());
    }

    @Override
    public Map<String, Object> getStudentMatchingStatistics(Long studentId)
    {
        Map<String, Object> statistics = new HashMap<>();
        
        List<CrMatchingRecord> records = crMatchingRecordMapper.selectStudentMatchingRecords(studentId, null);
        statistics.put("totalMatches", records.size());

        long activeCount = records.stream().filter(r -> "Y".equals(r.getIsRecommended())).count();
        long viewedCount = records.stream().filter(r -> r.getMatchScore() != null).count();
        long appliedCount = records.stream().filter(r -> r.getRecommendationReason() != null).count();

        statistics.put("activeRecommendations", activeCount);
        statistics.put("viewedRecommendations", viewedCount);
        statistics.put("appliedRecommendations", appliedCount);

        return statistics;
    }

    @Override
    public Map<String, Object> getClubMatchingStatistics(Long clubId)
    {
        Map<String, Object> statistics = new HashMap<>();
        
        List<CrMatchingRecord> records = crMatchingRecordMapper.selectClubMatchingRecords(clubId, null);
        statistics.put("totalMatches", records.size());

        long activeCount = records.stream().filter(r -> "Y".equals(r.getIsRecommended())).count();
        statistics.put("potentialCandidates", activeCount);
        
        // 已查看数量统计（由于实体类中没有isViewed字段，暂时统计空值）
        long viewedCount = records.stream().filter(r -> r.getRecommendationReason() != null && !r.getRecommendationReason().isEmpty()).count();
        statistics.put("viewedCount", viewedCount);
        
        // 计算平均匹配分数
        if (!records.isEmpty()) {
            double avgScore = records.stream()
                .mapToDouble(m -> m.getMatchScore() != null ? m.getMatchScore().doubleValue() : 0)
                .average().orElse(0);
            statistics.put("averageScore", avgScore);
        } else {
            statistics.put("averageScore", 0);
        }

        // 高分匹配统计（80分以上）
        long highScoreCount = records.stream()
            .filter(m -> m.getMatchScore() != null && m.getMatchScore().compareTo(new BigDecimal(80)) >= 0)
            .count();
        statistics.put("highScoreCount", highScoreCount);
        
        return statistics;
    }

    public List<CrMatchingRecord> selectBestMatchedStudents(Long clubId, Long recruitmentId, int limit)
    {
        return crMatchingRecordMapper.selectBestMatchedStudents(clubId, recruitmentId, limit);
    }

    @Override
    public Map<String, Object> getRecruitmentMatchingStatistics(Long recruitmentId)
    {
        Map<String, Object> statistics = new HashMap<>();
        
        List<CrMatchingRecord> records = selectMatchingsByRecruitmentId(recruitmentId, null);
        statistics.put("totalMatches", records.size());

        return statistics;
    }

    @Override
    public Map<String, Object> getMatchingScoreDistribution()
    {
        Map<String, Object> distribution = new HashMap<>();
        
        List<CrMatchingRecord> allRecords = crMatchingRecordMapper.selectScoreDistribution(null);
        
        long range90_100 = allRecords.stream().filter(r -> r.getMatchScore() != null && 
                r.getMatchScore().compareTo(new BigDecimal("90")) >= 0).count();

        distribution.put("range90_100", range90_100);

        return distribution;
    }

    // Implement remaining methods with simplified logic
    /**
     * 生成推荐理由
     */
    private String generateRecommendationReason(BigDecimal skillScore, BigDecimal interestScore, 
                                             BigDecimal timeScore, CrRecruitment recruitment) {
        StringBuilder reason = new StringBuilder();
        
        // 根据各项分数生成推荐理由
        if (skillScore.compareTo(new BigDecimal("80")) >= 0) {
            reason.append("您的技能与该职位要求高度匹配，");
        } else if (skillScore.compareTo(new BigDecimal("60")) >= 0) {
            reason.append("您的技能与该职位要求基本匹配，");
        }
        
        if (interestScore.compareTo(new BigDecimal("80")) >= 0) {
            reason.append("对该社团表现出浓厚兴趣，");
        } else if (interestScore.compareTo(new BigDecimal("60")) >= 0) {
            reason.append("对该社团有一定兴趣，");
        }
        
        if (timeScore.compareTo(new BigDecimal("80")) >= 0) {
            reason.append("时间安排契合度高，");
        } else if (timeScore.compareTo(new BigDecimal("60")) >= 0) {
            reason.append("时间安排基本契合，");
        }
        
        // 添加职位和社团信息
        reason.append("强烈推荐您申请")
              .append(recruitment.getClubName())
              .append("的")
              .append(recruitment.getTitle())
              .append("职位。");
        
        return reason.toString();
    }
    
    /**
     * 生成匹配详情（JSON格式）
     */
    private String generateMatchDetails(BigDecimal skillScore, BigDecimal interestScore, 
                                      BigDecimal timeScore, BigDecimal otherScore) {
        try {
            Map<String, Object> details = new HashMap<>();
            details.put("skillMatch", skillScore);
            details.put("interestMatch", interestScore);
            details.put("timeMatch", timeScore);
            details.put("otherFactors", otherScore);
            
            // 添加评分等级
            details.put("skillLevel", getScoreLevel(skillScore));
            details.put("interestLevel", getScoreLevel(interestScore));
            details.put("timeLevel", getScoreLevel(timeScore));
            details.put("otherLevel", getScoreLevel(otherScore));
            
            // 添加权重信息
            details.put("skillWeight", "0.4");
            details.put("interestWeight", "0.3");
            details.put("timeWeight", "0.2");
            details.put("otherWeight", "0.1");
            
            return new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(details);
        } catch (Exception e) {
            log.error("生成匹配详情时出错：{}", e.getMessage());
            return "{}";
        }
    }
    
    /**
     * 获取评分等级
     */
    private String getScoreLevel(BigDecimal score) {
        if (score.compareTo(new BigDecimal("90")) >= 0) {
            return "优秀";  // excellent
        } else if (score.compareTo(new BigDecimal("80")) >= 0) {
            return "良好";  // good
        } else if (score.compareTo(new BigDecimal("70")) >= 0) {
            return "一般";  // average
        } else if (score.compareTo(new BigDecimal("60")) >= 0) {
            return "及格";  // pass
        } else {
            return "较差";  // poor
        }
    }

    @Override
    @Transactional
    public int recalculateMatching(Long matchingId) { return 1; }

    @Override
    @Transactional
    public int batchRecalculateMatchings(Long studentId, Long recruitmentId) { return 1; }

    @Override
    @Transactional
    public int viewMatchingRecommendation(Long matchingId, Long studentId) { return 1; }

    @Override
    @Transactional
    public int submitMatchingFeedback(Long matchingId, Long studentId, String feedback, Boolean isAccurate) { return 1; }

    /**
     * 社团查看匹配推荐
     * 
     * @param matchingId 匹配记录ID
     * @param clubId 社团ID
     * @return 结果
     */
    @Override
    @Transactional
    public int viewClubRecommendation(Long matchingId, Long clubId)
    {
        // 验证匹配记录是否存在
        CrMatchingRecord matchingRecord = crMatchingRecordMapper.selectCrMatchingRecordByRecordId(matchingId);
        if (matchingRecord == null) {
            throw new RuntimeException("匹配记录不存在");
        }

        // 验证是否是本社团的匹配记录
        if (!matchingRecord.getClubId().equals(clubId)) {
            throw new RuntimeException("只能查看本社团的匹配推荐");
        }

        // 由于实体类中没有isViewed和viewTime字段，暂时只返回成功状态
        return 1;
    }

    @Override
    public Map<String, Object> getRecommendationAnalysis() { return new HashMap<>(); }

    @Override
    @Transactional
    public int cleanupExpiredMatchings(int days) { return 0; }

    @Override
    public List<CrMatchingRecord> exportMatchingRecords(CrMatchingRecord crMatchingRecord) { 
        return crMatchingRecordMapper.selectCrMatchingRecordList(crMatchingRecord); 
    }
}